<?php
/**
 * @link https://gitee.com/toshcn/yii2-oauth2-server
 * @copyright Copyright (c) 2018 len168.com
 * @license https://gitee.com/toshcn/yii2-oauth2-server/blob/master/LICENSE
 */

namespace toshcn\yii2\oauth2server;

use \Yii;
use \yii\i18n\PhpMessageSource;

/**
 * oauth2server module definition class
 */
class Module extends \yii\base\Module
{
    const VERSION = '1.0.0';

    public $layout = 'main';

    public $controllerNamespace = 'toshcn\yii2\oauth2server\controllers';

    /**
     * @var array Model's map
     */
    public $modelMap = [];

    /**
     * @var array Storage's map
     */
    public $storageMap = [];

    /**
     * @var array GrantTypes collection
     */
    public $grantTypes = [];

    /**
     * @var string name of access token parameter
     */
    public $tokenParamName;

    /**
     * @var type max access lifetime
     */
    public $tokenAccessLifetime;

    /**
     * @var string User's login action
     */
    public $loginAction = '/oauth2/authorize/login';

    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();
        $this->registerTranslations();
    }

    /**
     * Gets Oauth2 Server
     *
     * @return \toshcn\yii2\oauth2server\Server
     * @throws \ReflectionException
     * @throws \yii\base\InvalidConfigException
     * @throws \yii\di\NotInstantiableException
     */
    public function getServer()
    {
        if(!$this->has('server')) {
            $storages = [];
            foreach(array_keys($this->storageMap) as $name) {
                $storages[$name] = \Yii::$container->get($name);
            }

            $grantTypes = [];
            foreach($this->grantTypes as $name => $options) {
                if(!isset($storages[$name]) || empty($options['class'])) {
                    throw new \yii\base\InvalidConfigException('Invalid grant types configuration.');
                }

                $class = $options['class'];
                unset($options['class']);

                $reflection = new \ReflectionClass($class);
                $config = array_merge([0 => $storages[$name]], [$options]);

                $instance = $reflection->newInstanceArgs($config);
                $grantTypes[$name] = $instance;
            }

            $server = Yii::$container->get(Server::className(), [
                $this,
                $storages,
                [
                    'token_param_name' => $this->tokenParamName,
                    'access_lifetime' => $this->tokenAccessLifetime,
                    /** add more ... [see Oauth2->storageMap] */
                ],
                $grantTypes
            ]);

            $this->set('server', $server);
        }
        return $this->get('server');
    }

    public function getRequest()
    {
        if(!$this->has('request')) {
            $this->set('request', Request::createFromGlobals());
        }
        return $this->get('request');
    }

    public function getResponse()
    {
        if(!$this->has('response')) {
            $this->set('response', new Response());
        }
        return $this->get('response');
    }

    /**
     * 配置消息翻译
     * Register translations for this module
     *
     * @return void
     * @throws \yii\base\InvalidConfigException
     */
    public function registerTranslations()
    {
        if(!isset(Yii::$app->get('i18n')->translations['open/modules/oauth2/*'])) {
            Yii::$app->get('i18n')->translations['open/modules/oauth2/*'] = [
                'class'    => PhpMessageSource::className(),
                'basePath' => __DIR__ . '/messages',
                'fileMap' => [
                    'open/modules/oauth2/common' => 'common.php'
                ]
            ];
        }
    }

    /**
     * Translate module message
     *
     * @param string $category
     * @param string $message
     * @param array $params
     * @param string $language
     * @return string
     */
    public static function t($category, $message, $params = [], $language = null)
    {
        return Yii::t('open/modules/oauth2/' . $category, $message, $params, $language);
    }
}
